package models;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import models.msgs.*;
import models.msgs.Number;
import play.Logger;
import play.mvc.*;
import play.libs.*;
import play.libs.F.*;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import adapter.GameThread;
import akka.actor.*;
import static akka.pattern.Patterns.ask;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;

import static java.util.concurrent.TimeUnit.*;

public class Human extends UntypedActor
{
    public final String name;
    public final ActorRef table;
    public String idGracza;
    static String Help = "<br />Tworzenie gry: CreateGame (liczba graczy: 2-4) (liczba botow: 0-4) (czy host gra: 0-n 1-y)<br />"
    +"(ilosc poczatkowa pieniedzy) (stawka wejsciowa) <br />"
    +"Dolaczanie do gry: Join (id gry do ktorej chcesz sie dolaczyc)<br />"
    +"Wyswietlenie listy gier: Refresh<br />"
    +"Rozpoczecie gry jesli jest sie hostem: StartGame<br />"
    +"Wyjscie z gry: Leave<br />"
    +"Ranking w grze: Ranking<br />" 
    +"Wymiana kart: ChangeCards (numer karty liczonej od 0) - max 4<br />"
    +"Kolejna runda jesli jest sie hostem: KolejnaRunda<br /><br />"
    +"Polecenia licytacji:<br />"
    +"Przebicie o iles stawki: Raise (o ile przebić)<br />"
    +"Wyrowniae do stawki: Call<br />"
    +"Zrezygnowanie z gry: Fold<br />"
    +"Allin: All-in<br />" 
    +"Ranking w grze: Ranking<br />";

    protected WebSocket.In<JsonNode>  in;
    protected WebSocket.Out<JsonNode> out;
    
    private String FazaGry;

    public Human(String _name, WebSocket.In<JsonNode> _in,
            WebSocket.Out<JsonNode> _out, ActorRef _table)
    {
        name = _name;        
        table = _table;
        in = _in;
        out = _out;
        FazaGry = "Lob";
        //gameThread = new GameThread();
        

        in.onMessage(new Callback<JsonNode>()
        {
            @Override
            public void invoke(JsonNode event)
            {
                try
                {
                	//int nr = event.get("nr").asInt(); 
                	String nr = event.get("nr").asText();
                	getSelf().tell(new String(nr), getSelf() );                	
                }
                catch (Exception e)
                {
                    Logger.error("invokeError");
                }
                
            }
        });

        in.onClose(new Callback0()
        {
            @Override
            public void invoke()
            {
                table.tell(new Quit(name), getSelf() );
            }
        });
    }

    @Override
    public void preStart()
    {        
        String text = "my Actor is now running!";
    	table.tell(new Info(text, name), getSelf()); 
    }

    @Override
    public void postStop()
    {
        String text = "I've been killed";
    	table.tell(new Info(text, name), getSelf()); 
    }

    @Override
    public void onReceive(Object msg) throws Exception
    {
 
            if (msg instanceof String)
            {   
            	String talk = (String)msg;
            	String text = talk;
            	
            	try{ talk=talk.substring(0, talk.indexOf(" ")); } catch(StringIndexOutOfBoundsException e) {}
            	try{
            	switch(talk) {
                  case "CreateGame":   table.tell(new Task(TaskCreator.NewGame(text), name), getSelf());
                                       break;
                  case "Join":         table.tell(new Task(TaskCreator.Join(text), name), getSelf());
                                       break;
                  case "Refresh":      table.tell(new Task("S_REFRESH", name), getSelf());
                                       break;
                  case "StartGame":    table.tell(new Task("G_START", name), getSelf());
                                       break;
                  case "LeaveGame":    table.tell(new Task("G_LEAVE", name), getSelf());
                  					   Table.idmembers.remove(idGracza);
                                       getSelf().tell(new EventMsg("LEAVE", name), getSelf());
                                       break;
                  case "ChangeCards":  table.tell(new Task(TaskCreator.Wymiana(text), name), getSelf());
                                       break;
                  case "KolejnaRunda": table.tell(new Task("G_NEW", name), getSelf());
                                       break;
                  case "Check":        table.tell(new Task("G_CHECK", name), getSelf());
                                       break;
                  case "Bet":          table.tell(new Task(TaskCreator.Raise(text), name), getSelf());
                                       break;
                  case "Raise":        table.tell(new Task(TaskCreator.Raise(text), name), getSelf());
                                       break;
                  case "Call":         table.tell(new Task("G_CALL", name), getSelf());
                                       break;
                  case "Fold":         table.tell(new Task("G_FOLD", name), getSelf());
                                       break;
                  case "Allin":        table.tell(new Task("G_ALLIN", name), getSelf());
                                       break;
                  case "Ranking":      table.tell(new Task("G_RANKING", name), getSelf());
                  					   break;
                  case "Help":         table.tell(new Info(Help, name), getSelf());
					   				   break;
                  default:             Table.notifyAll(new Info(text, name));
                  					   break;
                }
            	}
            	catch(Exception ex) {
            	  ObjectNode event = Json.newObject();
                  event.put("message", "Nieprawidlowa komenda");
                  out.write(event);
            	}
            }  
            else if (msg instanceof IDGracza)
            {
            	String id = ((IDGracza) msg).getId(); 
            	this.idGracza=id;
            	
            	ObjectNode event = Json.newObject();
            	
            	if(id.equals("0")) {
            	  getSelf().tell(new Info("Gra zostala utworzona","Table"), getSelf());
            	  event.put("message", "CREATEH");
    	          out.write(event);
            	}
            	else {
            	  getSelf().tell(new Info("Dolaczyles do gry","Table"), getSelf());
            	  event.put("message", "CREATE");
    	          out.write(event);
            	}
            }
            else if(msg instanceof EventMsg)
            {        
            	String eventmsg = ((EventMsg) msg).getEvent();
            	String name = ((EventMsg) msg).getName();    
	            ObjectNode event = Json.newObject();
	            
	            if(eventmsg.equals("ALL")) {
	              if(idGracza.equals("0")) eventmsg+="H";
	            }
	            if(eventmsg.equals("BID") && this.name!=name) {
	              eventmsg="CREATE";
	            }
	            if(eventmsg.equals("CARDS")) {
	              event.put("deck", name); 
	            }
	            
	            event.put("message", eventmsg); 
	            
	            out.write(event);
            }
            else if(msg instanceof Info)
            {        
            	Info info = (Info) msg;             	
	            ObjectNode event = Json.newObject();
	            event.put("message", "[ "+ info.getName()+ " ] : " + info.getText()); 
	            
	            out.write(event);
            }
            else {
                unhandled(msg);
            }
            
        }
    
    /**
     * Zwraca NazweKlienta.
     * @return name.
     */
    public String getName() {
  	  return name;
    }       
}

